home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / perl / perl5a1.lha / perl5alpha1 / do / subst < prev    next >
Encoding:
Text File  |  1992-08-15  |  6.9 KB  |  270 lines

  1. int
  2. do_subst(TARG,arg,sp)
  3. STR *TARG;
  4. ARG *arg;
  5. int sp;
  6. {
  7.     register SPAT *spat;
  8.     SPAT *rspat;
  9.     register STR *dstr;
  10.     register char *s = str_get(TARG);
  11.     char *strend = s + TARG->str_cur;
  12.     register char *m;
  13.     char *c;
  14.     register char *d;
  15.     int clen;
  16.     int iters = 0;
  17.     int maxiters = (strend - s) + 10;
  18.     register int i;
  19.     bool once;
  20.     char *orig;
  21.     int safebase;
  22.  
  23.     rspat = spat = arg[2].arg_ptr.arg_spat;
  24.     if (!spat || !s)
  25.     fatal("panic: do_subst");
  26.     else if (spat->spat_runtime) {
  27.     nointrp = "|)";
  28.     (void)eval(spat->spat_runtime,G_SCALAR,sp);
  29.     m = str_get(dstr = stack->ary_array[sp+1]);
  30.     nointrp = "";
  31.     if (spat->spat_regexp) {
  32.         regfree(spat->spat_regexp);
  33.         spat->spat_regexp = Null(REGEXP*);    /* required if regcomp pukes */
  34.     }
  35.     spat->spat_regexp = regcomp(m,m+dstr->str_cur,
  36.         spat->spat_flags & SPAT_FOLD);
  37.     if (spat->spat_flags & SPAT_KEEP) {
  38.         if (!(spat->spat_flags & SPAT_FOLD))
  39.         scanconst(spat, m, dstr->str_cur);
  40.         arg_free(spat->spat_runtime);    /* it won't change, so */
  41.         spat->spat_runtime = Nullarg;    /* no point compiling again */
  42.         hoistmust(spat);
  43.             if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) {
  44.                 curcmd->c_flags &= ~CF_OPTIMIZE;
  45.                 opt_arg(curcmd, 1, curcmd->c_type == C_EXPR);
  46.             }
  47.     }
  48.     }
  49. #ifdef DEBUGGING
  50.     if (debug & 8) {
  51.     deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
  52.     }
  53. #endif
  54.     safebase = ((!spat->spat_regexp || !spat->spat_regexp->nparens) &&
  55.       !sawampersand);
  56.     if (!spat->spat_regexp->prelen && lastspat)
  57.     spat = lastspat;
  58.     orig = m = s;
  59.     if (hint) {
  60.     if (hint < s || hint > strend)
  61.         fatal("panic: hint in do_match");
  62.     s = hint;
  63.     hint = Nullch;
  64.     if (spat->spat_regexp->regback >= 0) {
  65.         s -= spat->spat_regexp->regback;
  66.         if (s < m)
  67.         s = m;
  68.     }
  69.     else
  70.         s = m;
  71.     }
  72.     else if (spat->spat_short) {
  73.     if (spat->spat_flags & SPAT_SCANFIRST) {
  74.         if (TARG->str_pok & SP_STUDIED) {
  75.         if (screamfirst[spat->spat_short->str_rare] < 0)
  76.             goto nope;
  77.         else if (!(s = screaminstr(TARG,spat->spat_short)))
  78.             goto nope;
  79.         }
  80. #ifndef lint
  81.         else if (!(s = fbminstr((unsigned char*)s, (unsigned char*)strend,
  82.           spat->spat_short)))
  83.         goto nope;
  84. #endif
  85.         if (s && spat->spat_regexp->regback >= 0) {
  86.         ++spat->spat_short->str_u.str_useful;
  87.         s -= spat->spat_regexp->regback;
  88.         if (s < m)
  89.             s = m;
  90.         }
  91.         else
  92.         s = m;
  93.     }
  94.     else if (!multiline && (*spat->spat_short->str_ptr != *s ||
  95.       bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
  96.         goto nope;
  97.     if (--spat->spat_short->str_u.str_useful < 0) {
  98.         str_free(spat->spat_short);
  99.         spat->spat_short = Nullstr;    /* opt is being useless */
  100.     }
  101.     }
  102.     once = !(rspat->spat_flags & SPAT_GLOBAL);
  103.     if (rspat->spat_flags & SPAT_CONST) {    /* known replacement string? */
  104.     if ((rspat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
  105.         dstr = rspat->spat_repl[1].arg_ptr.arg_str;
  106.     else {                    /* constant over loop, anyway */
  107.         (void)eval(rspat->spat_repl,G_SCALAR,sp);
  108.         dstr = stack->ary_array[sp+1];
  109.     }
  110.     c = str_get(dstr);
  111.     clen = dstr->str_cur;
  112.     if (clen <= spat->spat_regexp->minlen) {
  113.                     /* can do inplace substitution */
  114.         if (regexec(spat->spat_regexp, s, strend, orig, 0,
  115.           TARG->str_pok & SP_STUDIED ? TARG : Nullstr, safebase)) {
  116.         if (spat->spat_regexp->subbase) /* oops, no we can't */
  117.             goto long_way;
  118.         d = s;
  119.         lastspat = spat;
  120.         TARG->str_pok = SP_VALID;    /* disable possible screamer */
  121.         if (once) {
  122.             m = spat->spat_regexp->startp[0];
  123.             d = spat->spat_regexp->endp[0];
  124.             s = orig;
  125.             if (m - s > strend - d) {    /* faster to shorten from end */
  126.             if (clen) {
  127.                 Copy(c, m, clen, char);
  128.                 m += clen;
  129.             }
  130.             i = strend - d;
  131.             if (i > 0) {
  132.                 Move(d, m, i, char);
  133.                 m += i;
  134.             }
  135.             *m = '\0';
  136.             TARG->str_cur = m - s;
  137.             STABSET(TARG);
  138.             str_numset(ARGTARG, 1.0);
  139.             stack->ary_array[++sp] = ARGTARG;
  140.             return sp;
  141.             }
  142.             /*SUPPRESS 560*/
  143.             else if (i = m - s) {    /* faster from front */
  144.             d -= clen;
  145.             m = d;
  146.             str_chop(TARG,d-i);
  147.             s += i;
  148.             while (i--)
  149.                 *--d = *--s;
  150.             if (clen)
  151.                 Copy(c, m, clen, char);
  152.             STABSET(TARG);
  153.             str_numset(ARGTARG, 1.0);
  154.             stack->ary_array[++sp] = ARGTARG;
  155.             return sp;
  156.             }
  157.             else if (clen) {
  158.             d -= clen;
  159.             str_chop(TARG,d);
  160.             Copy(c,d,clen,char);
  161.             STABSET(TARG);
  162.             str_numset(ARGTARG, 1.0);
  163.             stack->ary_array[++sp] = ARGTARG;
  164.             return sp;
  165.             }
  166.             else {
  167.             str_chop(TARG,d);
  168.             STABSET(TARG);
  169.             str_numset(ARGTARG, 1.0);
  170.             stack->ary_array[++sp] = ARGTARG;
  171.             return sp;
  172.             }
  173.             /* NOTREACHED */
  174.         }
  175.         do {
  176.             if (iters++ > maxiters)
  177.             fatal("Substitution loop");
  178.             m = spat->spat_regexp->startp[0];
  179.             /*SUPPRESS 560*/
  180.             if (i = m - s) {
  181.             if (s != d)
  182.                 Move(s,d,i,char);
  183.             d += i;
  184.             }
  185.             if (clen) {
  186.             Copy(c,d,clen,char);
  187.             d += clen;
  188.             }
  189.             s = spat->spat_regexp->endp[0];
  190.         } while (regexec(spat->spat_regexp, s, strend, orig, s == m,
  191.             Nullstr, TRUE));    /* (don't match same null twice) */
  192.         if (s != d) {
  193.             i = strend - s;
  194.             TARG->str_cur = d - TARG->str_ptr + i;
  195.             Move(s,d,i+1,char);        /* include the Null */
  196.         }
  197.         STABSET(TARG);
  198.         str_numset(ARGTARG, (double)iters);
  199.         stack->ary_array[++sp] = ARGTARG;
  200.         return sp;
  201.         }
  202.         str_numset(ARGTARG, 0.0);
  203.         stack->ary_array[++sp] = ARGTARG;
  204.         return sp;
  205.     }
  206.     }
  207.     else
  208.     c = Nullch;
  209.     if (regexec(spat->spat_regexp, s, strend, orig, 0,
  210.       TARG->str_pok & SP_STUDIED ? TARG : Nullstr, safebase)) {
  211.     long_way:
  212.     dstr = Str_new(25,str_len(TARG));
  213.     str_nset(dstr,m,s-m);
  214.     if (spat->spat_regexp->subbase)
  215.         curspat = spat;
  216.     lastspat = spat;
  217.     do {
  218.         if (iters++ > maxiters)
  219.         fatal("Substitution loop");
  220.         if (spat->spat_regexp->subbase
  221.           && spat->spat_regexp->subbase != orig) {
  222.         m = s;
  223.         s = orig;
  224.         orig = spat->spat_regexp->subbase;
  225.         s = orig + (m - s);
  226.         strend = s + (strend - m);
  227.         }
  228.         m = spat->spat_regexp->startp[0];
  229.         str_ncat(dstr,s,m-s);
  230.         s = spat->spat_regexp->endp[0];
  231.         if (c) {
  232.         if (clen)
  233.             str_ncat(dstr,c,clen);
  234.         }
  235.         else {
  236.         char *mysubbase = spat->spat_regexp->subbase;
  237.  
  238.         spat->spat_regexp->subbase = Nullch;    /* so recursion works */
  239.         (void)eval(rspat->spat_repl,G_SCALAR,sp);
  240.         str_scat(dstr,stack->ary_array[sp+1]);
  241.         if (spat->spat_regexp->subbase)
  242.             Safefree(spat->spat_regexp->subbase);
  243.         spat->spat_regexp->subbase = mysubbase;
  244.         }
  245.         if (once)
  246.         break;
  247.     } while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr,
  248.         safebase));
  249.     str_ncat(dstr,s,strend - s);
  250.     str_replace(TARG,dstr);
  251.     STABSET(TARG);
  252.     str_numset(ARGTARG, (double)iters);
  253.     stack->ary_array[++sp] = ARGTARG;
  254.     return sp;
  255.     }
  256.     str_numset(ARGTARG, 0.0);
  257.     stack->ary_array[++sp] = ARGTARG;
  258.     return sp;
  259.  
  260. nope:
  261.     ++spat->spat_short->str_u.str_useful;
  262.     str_numset(ARGTARG, 0.0);
  263.     stack->ary_array[++sp] = ARGTARG;
  264.     return sp;
  265. }
  266. #ifdef BUGGY_MSC
  267.  #pragma intrinsic(memcmp)
  268. #endif /* BUGGY_MSC */
  269.  
  270.